import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;

import metrics.NormalizedPRStatictic;
import metrics.PRStatistic;
import metrics.PrRcGraph;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldSelectorResult;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.jfree.ui.RefineryUtilities;

public class ShowRelevance {

	private static final String DOC_PATH = "TIME" + File.separator + "Docs";
	private static final String QUERY_PATH = "TIME" + File.separator
			+ "IR_2nd_Project_Queries";
	private static final String RELEVANCY_LIST = "TIME" + File.separator
			+ "RelevancyLists.txt";

	/**
	 * @param args
	 * @throws IOException
	 * @throws LockObtainFailedException
	 * @throws CorruptIndexException
	 * @throws ParseException
	 */
	public static void main(String[] args) throws CorruptIndexException,
			LockObtainFailedException, IOException, ParseException {
		StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
		Directory index = new RAMDirectory();

		IndexWriter writer = new IndexWriter(index, analyzer, true,
				IndexWriter.MaxFieldLength.UNLIMITED);

		readDirectoryIntoIndex(DOC_PATH, writer);
		writer.close();

		executeAllQueries(index, QUERY_PATH, analyzer);

	}

	/**
	 * Execute all queries contained in a folder (queryPath)
	 * @param index
	 * @param queryPath
	 * @param analyzer
	 * @throws ParseException
	 * @throws CorruptIndexException
	 * @throws IOException
	 */
	private static void executeAllQueries(Directory index, String queryPath,
			StandardAnalyzer analyzer) throws ParseException,
			CorruptIndexException, IOException {

		Vector<Query> queries = new Vector<Query>();

		Vector<PRStatistic> statistics = new Vector<PRStatistic>();
		Vector<String> mostRelevants = new Vector<String>(); 

		
		File directory = new File(queryPath);
		File files[] = directory.listFiles();

		for (File f : files) {
			if (!f.isDirectory()) {

				StringBuffer content = new StringBuffer();
				BufferedReader reader = null;
				try {
					reader = new BufferedReader(new FileReader(f));
					String line = "";

					while ((line = reader.readLine()) != null) {

						content.append(line).append(
								System.getProperty("line.separator"));

					}
					reader.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				Query q = new QueryParser(Version.LUCENE_30, "body",
						analyzer).parse(content.toString());
				queries.add(q);

			}

			RelevanceReference ref = new RelevanceReference(RELEVANCY_LIST);

			int currentQuery = 0;
			for (Query q : queries) {

				int hitsPerPage = 300;
				IndexSearcher searcher = new IndexSearcher(index, true);
				TopScoreDocCollector collector = TopScoreDocCollector.create(
						hitsPerPage, true);
				searcher.search(q, collector);
				ScoreDoc[] hits = collector.topDocs().scoreDocs;

				System.out.println("Found " + hits.length + " hits.");

				int relevantDocs = ref.relevantCountForQuery(currentQuery);
				int hitcount = 0;
				PRStatistic statistic = new PRStatistic();

				for (int i = 0; i < hits.length && hitcount < relevantDocs; ++i) {
					int docId = hits[i].doc;
					Document d = searcher.doc(docId);
					
					if (ref.isRelevant(d.get("title"), currentQuery)) {
						hitcount++;
						//System.out.println((i + 1) + ". " + d.get("title")+ " :-)");
					} else {
						//System.out.println((i + 1) + ". " + d.get("title") + " :-(");
					}
					statistic.addEntry(hitcount/(float)relevantDocs, hitcount/(float)(i+1));
					//System.out.println("recall:" + hitcount/(float)relevantDocs + " precision:" + hitcount/(float)(i+1));
				}
				
				//Most valuable result
				if(hits[0]!=null && searcher.doc(hits[0].doc)!=null) {
					String mvr = searcher.doc(hits[0].doc).get("title");
					mostRelevants.add(mvr);
				}
				else {
					mostRelevants.add(null);
				}
				
				
				statistics.add(statistic);
				
				
				searcher.close();
				currentQuery++;
			}

		}
		Vector<NormalizedPRStatictic> normalized = new Vector<NormalizedPRStatictic>();
		
		for (PRStatistic prStatistic : statistics) {
			normalized.add(prStatistic.getNormalizedVersion());
		}
		
		//Compute the Average
		NormalizedPRStatictic summary = new NormalizedPRStatictic();
		for(int i =0; i<=NormalizedPRStatictic.NORMALIZAION_PRECISION; i++) {
			float sum = 0;
			for (NormalizedPRStatictic statictic : normalized) {
				sum += statictic.getPrecisionOfEntry(i);
			}
			summary.addEntry((float)i/NormalizedPRStatictic.NORMALIZAION_PRECISION, sum/(float)normalized.size());
		}
		summary.showStatistics();
		summary.setLabel("First Round");
		
		RelevanceFeedback relevance = new RelevanceFeedback(queries, mostRelevants ,index);
		NormalizedPRStatictic try1 = relevance.getStatictics(0.5, 0.5);
		try1.setLabel("Relevance 0.5 0.5");
		
		NormalizedPRStatictic try2 = relevance.getStatictics(0.25, 0.75);
		try2.setLabel("Relevance 0.25 0.75");
		
		NormalizedPRStatictic try3 = relevance.getStatictics(0.75, 0.25);
		try3.setLabel("Relevance 0.75 0.25");
		
		
		//Show Graph
		Vector<NormalizedPRStatictic> entries = new Vector<NormalizedPRStatictic>();
		entries.add(summary);
		entries.add(try1);
		entries.add(try2);
		entries.add(try3);
		
		PrRcGraph graph = new PrRcGraph(entries);
        graph.pack();
        RefineryUtilities.centerFrameOnScreen(graph);
        graph.setVisible(true);
		
		
	}

	
	private static void getStatictics(double d, double e) {
		// TODO Auto-generated method stub
		
	}

	private static void readDirectoryIntoIndex(String folderPath,
			IndexWriter writer) throws CorruptIndexException, IOException {

		File directory = new File(folderPath);
		File files[] = directory.listFiles();

		for (File f : files) {
			if (!f.isDirectory()) {

				String name = f.getName();

				// read content of file
				StringBuffer content = new StringBuffer();
				BufferedReader reader = null;
				try {
					reader = new BufferedReader(new FileReader(f));
					String line = "";

					while ((line = reader.readLine()) != null) {

						content.append(line).append(
								System.getProperty("line.separator"));

					}
					reader.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

				addDoc(writer, name, content.toString());

			}

		}
	}

	private static void addDoc(IndexWriter writer, String title, String content)
			throws CorruptIndexException, IOException {
		Document doc = new Document();
		doc.add(new Field("title", title, Store.YES, Index.ANALYZED));
		doc.add(new Field("body", content.toLowerCase(), Store.YES,
				Index.ANALYZED));
		writer.addDocument(doc);
	}
}
